﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Globalization;

namespace CPA_Monitor
{
    public partial class Main : Form
    {
        delegate void NetworkUpdatedHandler(Networks.CPANetwork network);
        event NetworkUpdatedHandler NetworkUpdated;

        Communications communications = new Communications();
        Timer timerRefresh;
        string formTitle;

        int refreshTrigger = 1;

        class panelConnectivity
        {
            public string ID { get; set; }
            public bool Loading { get; set; }
        }

        public Main()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            formTitle = Text;
            Icon = CPA_Monitor.Properties.Resources.money_dollar;
            trackBarInterval.Value = Properties.Settings.Default.Interval;
            new Timer { Interval = 150, Enabled = true }.Tick += new EventHandler(LoadingIndicator_Tick);
            timerRefresh = new Timer { Interval = trackBarInterval.Value * 60000, Enabled = true };
            timerRefresh.Tick += new EventHandler(timerRefresh_Tick);
            NetworkUpdated += new NetworkUpdatedHandler(Main_NetworkUpdated);

            LoadNetworks();

            Refresh();
        }

        void LoadNetworks()
        {
            Networks.Load();
            panel1.Controls.Clear();
            foreach (Networks.CPANetwork network in Networks.NetworkEntries)
            {
                if (network.Enabled)
                {
                    var networkPanel = new StatsPanel();
                    panel1.Controls.Add(networkPanel);
                    networkPanel.groupBoxCPANetwork.Text = network.Company;
                    networkPanel.Dock = DockStyle.Top;
                    networkPanel.Tag = new panelConnectivity { ID = network.Company, Loading = true };
                    var worker = new BackgroundWorker();
                    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                    worker.RunWorkerAsync(network);
                }
                
            }
            Height = (panel1.Controls.Count * 75) + 88;
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            var cpaNetwork = e.Argument as Networks.CPANetwork;
            int refreshTriggerLast = 0;
            while (true)
            {
                if (refreshTrigger == refreshTriggerLast)
                {
                    System.Threading.Thread.Sleep(500);
                    continue;
                }

                refreshTriggerLast = refreshTrigger;

            GetStats:
                string result = cpaNetwork.StatsPostDataKeys == "" ? communications.PerformGet(cpaNetwork.StatsUrl) : communications.PerformPost(cpaNetwork.StatsUrl, cpaNetwork.GetPostDataStats());
                if ((cpaNetwork.LoggedInIndicator != "" && result.Contains(cpaNetwork.LoggedInIndicator)) || result == "") 
                  goto Login;
                var clicks = Regex.Match(result, cpaNetwork.RegexClicks).Groups["clicks"].Value;
                var profit = Regex.Match(result, cpaNetwork.RegexProfit).Groups["profit"].Value;
                var epc = Regex.Match(result, cpaNetwork.RegexEPC).Groups["epc"].Value;
                decimal profitValue;
                if (decimal.TryParse(profit, NumberStyles.Currency, null, out profitValue))
                {
                    profit = string.Format("{0:C}", profitValue);
                    decimal epcValue = profitValue == 0 ? 0 : profitValue / decimal.Parse(clicks);
                    epc = string.Format("{0:C}", epcValue);
                }
                if (cpaNetwork.Stats.Profit != profit) System.Media.SystemSounds.Exclamation.Play();
                cpaNetwork.Stats.Profit = profit;
                cpaNetwork.Stats.Clicks = clicks;
                cpaNetwork.Stats.EPC = epc;
                NetworkUpdated(cpaNetwork);
                continue;

            Login:
                var loginUrl = cpaNetwork.LoginUrl.Contains("|") ? cpaNetwork.LoginUrl.Split('|')[0] : cpaNetwork.LoginUrl;
                var loginPost = cpaNetwork.GetPostDataLogin();
                result = communications.PerformPost(loginUrl, loginPost);
                var loginAuthUrl = cpaNetwork.LoginUrl.Contains("|") ? communications.PerformPost(cpaNetwork.LoginUrl.Split('|')[1], loginPost) : "";
                goto GetStats;
            }
        }

        void Main_NetworkUpdated(Networks.CPANetwork network)
        {
            var statsPanel = panel1.Controls.Cast<StatsPanel>().Where(x => ((panelConnectivity)x.Tag).ID == network.Company).ToList()[0];
            ((panelConnectivity)statsPanel.Tag).Loading = false;
            statsPanel.labelProfit.Text = network.Stats.Profit;
            statsPanel.labelClicks.Text = network.Stats.Clicks + " Clicks";
            statsPanel.labelEPC.Text = network.Stats.EPC + " EPC";

            double total = 0;
            foreach (StatsPanel panel in panel1.Controls)
            {
                Text = formTitle + " $" + total.ToString();
                if (panel.labelProfit.Text.Contains("$"))
                    total += double.Parse(panel.labelProfit.Text, NumberStyles.Currency);
            }
            string newTitle = formTitle + " $" + total.ToString();
            if (Text != newTitle) Text = newTitle;
        }

        void timerRefresh_Tick(object sender, EventArgs e)
        {
            Refresh();
        }

        void LoadingIndicator_Tick(object sender, EventArgs e)
        {
            foreach (StatsPanel panel in panel1.Controls)
            {
                var connectivity = (panelConnectivity)panel.Tag;
                var newText = IndicateLoadIncrement(connectivity.ID, panel.groupBoxCPANetwork.Text, connectivity.Loading);
                if (panel.groupBoxCPANetwork.Text != newText) panel.groupBoxCPANetwork.Text = newText;
            }
        }

        string IndicateLoadIncrement(string name, string target, bool loading)
        {
            string loadingChars = @"—\|/";
            if (loading)
            {
                bool loadingStarted = false;
                for (int i = 0; i < loadingChars.Length; i++)
                {
                    if (target.Contains(loadingChars[i]))
                    {
                        loadingStarted = true;
                        target = name + " " + loadingChars[i == loadingChars.Length - 1 ? 0 : i + 1];
                        break;
                    }
                }
                if (!loadingStarted) target += " " + loadingChars[0];
            }
            else target = name;

            return target;
        }

        private void Refresh(object sender = null, EventArgs e = null)
        {
            foreach (StatsPanel panel in panel1.Controls)
            {
                ((panelConnectivity)panel.Tag).Loading = true;
            }

            timerRefresh.Stop();
            timerRefresh.Start();

            refreshTrigger++;
        }

        private void buttonNetworks_Click(object sender, EventArgs e)
        {
            var dialog = new EditNetworks();
            dialog.ShowDialog();
            if (dialog.ChangesOccured)
            {
                MessageBox.Show("Application will now restart");
                Application.Restart();
            }
        }

        private void trackBarInterval_ValueChanged(object sender, EventArgs e)
        {
            labelIntervalValue.Text = trackBarInterval.Value + (trackBarInterval.Value == 1 ? " minute" : " minutes");
        }

        private void trackBarInterval_MouseUp(object sender, MouseEventArgs e)
        {
            Properties.Settings.Default.Interval = trackBarInterval.Value;
            Properties.Settings.Default.Save();
            timerRefresh.Interval = trackBarInterval.Value * 60000;
        }


    }
}
